﻿/*
 * 作者: 谢中涞,博客园:http://www.cnblogs.com/xie-zhonglai
 * 欢迎转载,但请保留出处
 * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Xiezl.Common.LinqEx;

namespace Xiezl.Common.EFExpressions
{
    /// <summary>
    /// 二元运算查询条件
    /// </summary>
    /// <typeparam name="T">查询条件实体类型</typeparam>
    /// <typeparam name="TVal">需要比较的属性类型</typeparam>
    internal class BinanryEfExpression<T, TVal> : EFExpression<T>
        where T : class
        where TVal : IComparable
    {
        /// <summary>
        /// 定义条件的实体属性
        /// </summary>
        private Expression<Func<T, TVal>> property;

        /// <summary>
        /// 比较的值
        /// </summary>
        private TVal val;

        /// <summary>
        /// 二元运算符
        /// </summary>
        private EBinaryType binaryType;

        /// <summary>
        /// 实例化新的二元查询表达式
        /// </summary>
        /// <param name="property">定义条件的实体属性</param>
        /// <param name="binaryType">二元运算符</param>
        /// <param name="val">比较的值</param>
        public BinanryEfExpression(Expression<Func<T, TVal>> property, EBinaryType binaryType, TVal val)
        {
            if (property == null)
                throw new ArgumentNullException("property");
            //if (val == null && binaryType != EBinaryType.Like)
            //    throw new ArgumentNullException("val");
            this.property = property;
            this.val = val;
            this.binaryType = binaryType;
        }

        internal override Expression Expression
        {
            get
            {
                if (_Expression == null)
                {
                    var propertyBody = GetMemberExpression(this, property);

                    Type type = typeof(TVal);
                    Expression compareVal = Expression.Constant(val);
                    //如果是Nullable类型，则把value转化成Nullable类型
                    if (type.IsNullableType())
                    {
                        compareVal = Expression.Convert(compareVal, type);
                    }
                    Expression tempExp = null;
                    switch (binaryType)
                    {
                        case EBinaryType.Equal:
                            tempExp = Expression.Equal(propertyBody, compareVal);
                            break;
                        case EBinaryType.GreaterThan:
                            tempExp = Expression.GreaterThan(propertyBody, compareVal);
                            break;
                        case EBinaryType.GreaterThanOrEqual:
                            tempExp = Expression.GreaterThanOrEqual(propertyBody, compareVal);
                            break;
                        case EBinaryType.LessThan:
                            tempExp = Expression.LessThan(propertyBody, compareVal);
                            break;
                        case EBinaryType.LessThanOrEqual:
                            tempExp = Expression.LessThanOrEqual(propertyBody, compareVal);
                            break;
                        case EBinaryType.NotEqual:
                            tempExp = Expression.NotEqual(propertyBody, compareVal);
                            break;
                        default:
                            break;
                    }
                    _Expression = tempExp;
                }
                return _Expression;
            }
        }
    }
}
